<template>
  <div>
    <div class="playedu-main-top mb-24">
      <div class="d-flex">
        <PerButton
          type="primary"
          text="新建分类"
          class="mr-16"
          :icon="h(PlusOutlined)"
          p="resource-category"
          @click="setCreateVisible(true)"
        />
      </div>
    </div>

    <div class="playedu-main-body">
      <div v-if="init" class="float-left text-center mt-30">
        <Spin />
      </div>

      <div
        class="playedu-tree"
        :style="{ display: init ? 'none' : 'block', width: '366px' }"
      >
        <Tree
          v-if="treeData.length > 0"
          :tree-data="treeData"
          draggable
          block-node
          @select="onSelect"
          @dragenter="onDragEnter"
          @drop="onDrop"
          :switcher-icon="switcherIcon"
        >
          <template #title="{ dataRef }">
            <div class="tree-node">
              <span class="tree-node-text">{{ dataRef.name }}</span>
              <div class="tree-node-actions">
                <Tooltip placement="top" title="可拖拽排序">
                  <i class="iconfont icon-icon-drag" />
                </Tooltip>
                <i
                  v-if="through('resource-category')"
                  class="iconfont icon-icon-edit"
                  @click="handleEdit(dataRef.key)"
                />
                <i
                  class="iconfont icon-icon-delete"
                  @click="handleDelete(dataRef.key, dataRef.name)"
                />
              </div>
            </div>
          </template>
        </Tree>
      </div>

      <ResourceCategoryCreate
        :open="createVisible"
        @cancel="handleCreateCancel"
      />

      <ResourceCategoryUpdate
        :id="cid"
        :open="updateVisible"
        @cancel="handleUpdateCancel"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, h, computed } from 'vue'
import { Tree, Spin, Modal, message, Tooltip, Button } from 'ant-design-vue'
import { PlusOutlined, ExclamationCircleFilled } from '@ant-design/icons-vue'
import { useRouter } from 'vue-router'
import { useUserStore, useSystemStore } from '@/store'

import PerButton from '@/components/Common/permission-button.vue'
import ResourceCategoryCreate from './create.vue'
import ResourceCategoryUpdate from './update.vue'
import { resourceCategory } from '@/api/index'

interface Option {
  key: string | number;
  name: string,
  children?: Option[];
}

interface CategoriesBoxModel {
  [key: number]: Array<{ id: number; name: string }>;
}

const router = useRouter()
const userStore = useUserStore()
const systemStore = useSystemStore()
const { confirm } = Modal

const loading = ref<boolean>(true)
const init = ref(true)
const refresh = ref(false)
const treeData = ref<Option[]>([])
const selectKey = ref<number[]>([])
const createVisible = ref<boolean>(false)
const updateVisible = ref<boolean>(false)
const cid = ref<number>(0)
const [modal] = Modal.useModal()

const permissions = computed<Record<string, any>>(() => userStore.permissions || {})

onMounted(() => {
  getData()
})

watch(refresh, () => {
  getData()
})

const onSelect = (selectedKeys: any) => {
  selectKey.value = selectedKeys
}

const through = (p: string) => {
  return typeof permissions.value[p] !== 'undefined'
}

const getData = () => {
  loading.value = true
  resourceCategory.resourceCategoryList().then((res: any) => {
    const categories: CategoriesBoxModel = res.data.categories
    systemStore.saveCategoriesAction(res.data.categories)
    if (JSON.stringify(categories) !== '{}') {
      const new_arr: Option[] = buildTreeData(categories, 0)
      treeData.value = new_arr
    }
    loading.value = false
    init.value = false
  })
}

const buildTreeData = (categories: CategoriesBoxModel, id: number): Option[] => {
  const currentLevel = categories[id]
  if (!currentLevel) {
    return []
  }
  
  return currentLevel.map(item => ({
    key: item.id,
    name: item.name,
    children: categories[item.id] ? buildTreeData(categories, item.id) : undefined
  }))
}

const handleEdit = (id: number) => {
  cid.value = id
  setUpdateVisible(true)
}

const handleDelete = (id: number, name: string) => {
  if (id === 0) return
  removeItem(id, name)
}

const resetData = () => {
  treeData.value = []
  refresh.value = !refresh.value
}

const removeItem = (id: number, label: string) => {
  if (id === 0) {
    return
  }
  resourceCategory.checkDestroy(id).then((res: any) => {
    if (
      res.data.children &&
      res.data.children.length === 0 &&
      res.data.courses &&
      res.data.courses.length === 0 &&
      res.data.images &&
      res.data.images.length === 0 &&
      res.data.videos &&
      res.data.videos.length === 0
    ) {
      delUser(id)
    } else if (
      res.data.children &&
      res.data.children.length === 0 &&
      res.data.courses &&
      res.data.courses.length === 0 &&
      !res.data.images &&
      !res.data.videos
    ) {
      delUser(id)
    } else {
      if (res.data.children && res.data.children.length > 0) {
        modal.warning({
          title: '操作确认',
          centered: true,
          okText: '好的',
          content: h('p', [
            '此分类下包含',
            h('span', { class: 'c-red' }, `（${res.data.children.length}个子分类）`),
            '，请先解除关联再删除！'
          ])
        })
      } else {
        const contentElements: any[] = ['此分类已关联']
        
        if (res.data.courses && res.data.courses.length > 0) {
          contentElements.push(
            h(
              Button,
              {
                style: { paddingLeft: '4px', paddingRight: '4px' },
                type: 'link',
                danger: true,
                onClick: () => router.push(`/course?cid=${id}&label=${label}`)
              },
              `（${res.data.courses.length}个线上课程），`
            )
          )
        }
        
        if (res.data.videos && res.data.videos.length > 0) {
          contentElements.push(
            h(
              Button,
              {
                style: { paddingLeft: '4px', paddingRight: '4px' },
                type: 'link',
                danger: true,
                onClick: () => router.push(`/videos?cid=${id}&label=${label}`)
              },
              `（${res.data.videos.length}个视频文件），`
            )
          )
        }
        
        if (res.data.images && res.data.images.length > 0) {
          contentElements.push(
            h(
              Button,
              {
                style: { paddingLeft: '4px', paddingRight: '4px' },
                type: 'link',
                danger: true,
                onClick: () => router.push(`/images?cid=${id}&label=${label}`)
              },
              `（${res.data.images.length}个图片文件），`
            )
          )
        }
        
        contentElements.push('请先解除关联再删除！')
        
        modal.warning({
          title: '操作确认',
          centered: true,
          okText: '好的',
          content: h('p', contentElements)
        })
      }
    }
  })
}

const delUser = (id: any) => {
  confirm({
    title: '操作确认',
    icon: h(ExclamationCircleFilled),
    content: '确认删除此分类？',
    centered: true,
    okText: '确认',
    cancelText: '取消',
    onOk() {
      resourceCategory.destroyResourceCategory(id).then(() => {
        message.success('操作成功')
        resetData()
      })
    },
    onCancel() {
      console.log('Cancel')
    }
  })
}

const onDragEnter = (info: any) => {
  console.log(info)
}

const onDrop = (info: any) => {
  const dropKey = info.node.key
  const dragKey = info.dragNode.key
  const dropPos = info.node.pos.split('-')
  const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
  
  const loop = (
    data: any[],
    key: any,
    callback: (node: any, i: number, data: any[]) => void
  ) => {
    for (let i = 0; i < data.length; i++) {
      if (data[i].key === key) {
        return callback(data[i], i, data)
      }
      if (data[i].children) {
        loop(data[i].children!, key, callback)
      }
    }
  }
  
  const data = [...treeData.value]
  let isTop = false

  for (let i = 0; i < data.length; i++) {
    if (data[i]?.key === dragKey) {
      isTop = true
    }
  }

  let dragObj: any
  loop(data, dragKey, (item, index, arr) => {
    arr.splice(index, 1)
    dragObj = item
  })

  if (!info.dropToGap) {
    loop(data, dropKey, (item) => {
      item.children = item.children || []
      item.children.unshift(dragObj)
    })
  } else if (
    (info.node.children || []).length > 0 &&
    info.node.expanded &&
    dropPosition === 1
  ) {
    loop(data, dropKey, (item) => {
      item.children = item.children || []
      item.children.unshift(dragObj)
    })
  } else {
    let ar: any[] = []
    let i: number
    loop(data, dropKey, (_item, index, arr) => {
      ar = arr
      i = index
    })
    if (dropPosition === -1) {
      ar.splice(i!, 0, dragObj!)
    } else {
      ar.splice(i! + 1, 0, dragObj!)
    }
  }
  treeData.value = data
  submitDrop(isTop, data, dragKey)
}

const submitDrop = (isTop: boolean, data: any, key: any) => {
  let result = checkDropArr(data, key)
  if (result) {
    if (isTop) {
      resourceCategory.dropSameClass(result.ids).then(() => {
        console.log('ok')
      })
    } else {
      submitChildDrop(key, 0, result)
    }
  }
}

const submitChildDrop = (key: any, pid: any, ids: any) => {
  resourceCategory.dropDiffClass(key, pid, ids.ids).then(() => {
    console.log('ok')
  })
}

const checkDropArr = (data: any, key: any): any => {
  let ids: any[] = []
  let isSame = false
  for (let i = 0; i < data.length; i++) {
    ids.push(data[i].key)
    if (data[i].key === key) {
      isSame = true
    }
    if (data[i].children) {
      let res: any = checkDropArr(data[i].children, key)
      if (res) {
        submitChildDrop(key, data[i].key, res)
      }
    }
  }
  if (isSame) {
    return { key, ids }
  }
}

const setCreateVisible = (val: boolean) => {
  createVisible.value = val
}

const setUpdateVisible = (val: boolean) => {
  updateVisible.value = val
}

const handleCreateCancel = () => {
  setCreateVisible(false)
  refresh.value = !refresh.value
}

const handleUpdateCancel = () => {
  setUpdateVisible(false)
  refresh.value = !refresh.value
}

const switcherIcon = () => h('i', { class: 'iconfont icon-icon-fold c-gray' })
</script>

<style scoped>

.tree-node {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  min-width: 0;
  padding: 4px 0;
}

.tree-node-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

</style>